Skip to contentMethod: lambda$closeInstance$1(Object, InstanceVisitor)
1: /**
2: * Copyright (C) 2017 Czech Technical University in Prague
3: *
4: * This program is free software: you can redistribute it and/or modify it under
5: * the terms of the GNU General Public License as published by the Free Software
6: * Foundation, either version 3 of the License, or (at your option) any
7: * later version.
8: *
9: * This program is distributed in the hope that it will be useful, but WITHOUT
10: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12: * details. You should have received a copy of the GNU General Public License
13: * along with this program. If not, see <http://www.gnu.org/licenses/>.
14: */
15: package cz.cvut.kbss.jsonld.serialization.traversal;
16:
17: import cz.cvut.kbss.jsonld.common.BeanAnnotationProcessor;
18: import cz.cvut.kbss.jsonld.common.BeanClassProcessor;
19: import cz.cvut.kbss.jsonld.exception.JsonLdSerializationException;
20:
21: import java.lang.reflect.Field;
22: import java.util.*;
23:
24: public class ObjectGraphTraverser implements InstanceVisitor {
25:
26: private static final Object EMPTY_OBJECT = new Object();
27:
28: private final Set<InstanceVisitor> visitors = new HashSet<>(4);
29:
30: private Map<Object, Object> knownInstances;
31:
32: public void addVisitor(InstanceVisitor visitor) {
33: Objects.requireNonNull(visitor);
34: visitors.add(visitor);
35: }
36:
37: public void removeVisitor(InstanceVisitor visitor) {
38: visitors.remove(visitor);
39: }
40:
41: private void resetKnownInstances() {
42: this.knownInstances = new IdentityHashMap<>();
43: }
44:
45: public void traverse(Object instance) {
46: Objects.requireNonNull(instance);
47: resetKnownInstances();
48: try {
49: if (instance instanceof Collection) {
50: traverseCollection((Collection<?>) instance);
51: } else {
52: traverseImpl(instance);
53: }
54: } catch (IllegalAccessException e) {
55: throw new JsonLdSerializationException("Unable to extract field value.", e);
56: }
57: }
58:
59: private void traverseCollection(Collection<?> col) throws IllegalAccessException {
60: openCollection(col);
61: for (Object item : col) {
62: traverseImpl(item);
63: }
64: closeCollection(col);
65: }
66:
67: private void traverseImpl(Object instance) throws IllegalAccessException {
68: if (knownInstances.containsKey(instance)) {
69: visitKnownInstance(instance);
70: return;
71: }
72: openInstance(instance);
73: for (Field f : BeanAnnotationProcessor.getSerializableFields(instance)) {
74: final Object value = BeanClassProcessor.getFieldValue(f, instance);
75: visitField(f, value);
76: if (value != null && BeanAnnotationProcessor.isObjectProperty(f)) {
77: traverseObjectPropertyValue(value);
78: }
79: }
80: closeInstance(instance);
81: }
82:
83: private void traverseObjectPropertyValue(Object value) throws IllegalAccessException {
84: if (value instanceof Collection) {
85: final Collection<?> col = (Collection<?>) value;
86: openCollection(col);
87: for (Object elem : col) {
88: traverseImpl(elem);
89: }
90: closeCollection(col);
91: } else if (value.getClass().isArray()) {
92: throw new JsonLdSerializationException("Arrays are not supported, yet.");
93: } else {
94: traverseImpl(value);
95: }
96: }
97:
98: @Override
99: public void openInstance(Object instance) {
100: knownInstances.put(instance, EMPTY_OBJECT);
101: visitors.forEach(v -> v.openInstance(instance));
102: }
103:
104: @Override
105: public void closeInstance(Object instance) {
106: visitors.forEach(v -> v.closeInstance(instance));
107: }
108:
109: @Override
110: public void visitKnownInstance(Object instance) {
111: visitors.forEach(v -> v.visitKnownInstance((instance)));
112: }
113:
114: @Override
115: public void visitField(Field field, Object value) {
116: visitors.forEach(v -> v.visitField(field, value));
117: }
118:
119: @Override
120: public void openCollection(Collection<?> collection) {
121: visitors.forEach(v -> v.openCollection(collection));
122: }
123:
124: @Override
125: public void closeCollection(Collection<?> collection) {
126: visitors.forEach(v -> v.closeCollection(collection));
127: }
128: }